home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1996 March
/
EnigmA AMIGA RUN 05 (1996)(G.R. Edizioni)(IT)[!][issue 1996-03][Skylink CD IV].iso
/
earcd
/
comm2
/
kms20src.lha
/
KMSC
/
areas.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-14
|
46KB
|
1,696 lines
/**********************************
* KMS *
**********************************
* ©1992 by BlackMagic Software *
**********************************
* *
**********************************/
#include <KMS/KMS.h>
Prototype struct AreaNode *SetArea(UWORD);
Prototype UMSMsgNum SelectArea(STRPTR);
Prototype struct AreaNode *InsertArea(VOID);
Prototype VOID DeleteArea(struct AreaNode *);
Prototype BOOL EditArea(STRPTR, UWORD);
Prototype BOOL EditAreaInfo(struct AreaNode *);
Prototype BOOL RemoveArea(STRPTR);
Prototype BOOL ListAreas(STRPTR, UWORD);
Prototype BOOL PrintAreaInfo(struct AreaNode *, UBYTE);
Prototype BOOL ChangePath(STRPTR);
Prototype VOID CreatePath(struct AreaNode *);
Prototype struct AreaNode *ChangeArea(STRPTR);
Prototype STRPTR PathParse(STRPTR, STRPTR);
Prototype struct AreaNode *SeekAreaName(struct AreaNode *, STRPTR);
Prototype struct AreaNode *AreaSearch(STRPTR);
Prototype BOOL AreaModify(STRPTR, UWORD);
Prototype BOOL GlobalAreaChange(STRPTR, UWORD, UWORD, ULONG);
Prototype VOID TakeASem(BOOL);
Prototype VOID DropASem(VOID);
/*****************************
* Externe Globale Variablen *
*****************************/
extern struct KMSBase *KMSBase;
extern struct LocalConfig *KMS_LC;
extern UMSAccount MyUMSAccount;
extern STRPTR PPArg, PPArg2;
extern UBYTE ShutDown, Plop;
/*********************
* Globale Variablen *
*********************/
TEXT PathString[LEN_KMSPATH+1];
/********************************
* Area in Liste suchen *
* TakeASem() von außen nötig! *
********************************
* I: Area-Index *
* O: struct AreaNode * *
********************************/
/// "SetArea"
struct AreaNode *SetArea(UWORD idx)
{
struct AreaNode *apoint;
UWORD startidx = 0;
BOOL forward = TRUE;
if (!idx)
return NULL;
apoint = (struct AreaNode *)KMSBase->AreaList.mlh_Head;
if (KMS_LC->Session.CurrentArea)
{
startidx = KMS_LC->Session.CurrentArea->AreaData.ID;
apoint = KMS_LC->Session.CurrentArea;
}
if (idx == startidx)
return KMS_LC->Session.CurrentArea;
if (idx < startidx)
forward = FALSE;
if (apoint->Node.mln_Succ)
{
while(((forward && apoint->Node.mln_Succ) || (!forward && apoint->Node.mln_Pred)) && apoint->AreaData.ID != idx)
{
if (forward)
apoint = (struct AreaNode *)apoint->Node.mln_Succ;
else
apoint = (struct AreaNode *)apoint->Node.mln_Pred;
}
if (apoint->Node.mln_Succ && apoint->Node.mln_Pred)
return apoint;
else
return NULL;
}
else
{
SystemError("SetArea", "No AreaList!");
return NULL;
}
}
///
/**************************************
* Group-Flag in Area "mbname" setzen *
**************************************
* I: MsgBase-Name *
* O: Anzahl Msgs in Gruppe *
**************************************/
/// "SelectArea"
UMSMsgNum SelectArea(STRPTR mbname)
{
UMSMsgNum result;
/* Alle gesetzten Local-Flag 2 rücksetzen */
UMSSelectTags(MyUMSAccount, UMSTAG_SelReadLocal, TRUE,
UMSTAG_SelMask, KMSLSTATF_InGroup,
UMSTAG_SelMatch, KMSLSTATF_InGroup,
UMSTAG_SelWriteLocal, TRUE,
UMSTAG_SelUnset, KMSLSTATF_InGroup,
TAG_DONE);
/* Alle Nachrichten der aktuellen Gruppe für den User
mit Local-Flag 2 markieren */
if (!strcmp(mbname, "*KMS-GLOBAL*")) /* Global-Brett -> Alle Nachrichten erreichbar */
result =
UMSSelectTags(MyUMSAccount, UMSTAG_SelWriteLocal, TRUE,
UMSTAG_SelSet, KMSLSTATF_InGroup,
TAG_DONE);
else
result =
UMSSelectTags(MyUMSAccount, UMSTAG_WGroup, mbname,
UMSTAG_SelWriteLocal, TRUE,
UMSTAG_SelSet, KMSLSTATF_InGroup,
UMSTAG_SelQuick, TRUE,
TAG_DONE);
/* Für alle nicht sichtbaren Nachrichten Bit 2 wieder löschen */
UMSMsgNum result2 =
UMSSelectTags(MyUMSAccount, UMSTAG_SelReadLocal, TRUE,
UMSTAG_SelMask, KMSLSTATF_Visible|KMSLSTATF_InGroup,
UMSTAG_SelMatch, KMSLSTATF_InGroup,
UMSTAG_SelWriteLocal, TRUE,
UMSTAG_SelUnset, KMSLSTATF_InGroup,
TAG_DONE);
return result-result2;
}
///
/********************************
* Neue Areastruktur einrichten *
* TakeASem() von außen! *
********************************
* I: --- *
* O: struct AreaNode * *
********************************/
/// "InsertArea"
struct AreaNode *InsertArea(VOID)
{
struct AreaNode *apoint, *newapoint;
UWORD id = 0, previd = 0;
apoint = (struct AreaNode *)KMSBase->AreaList.mlh_TailPred;
if (!apoint->Node.mln_Pred)
{
SystemError("InsertArea", "No AreaList!");
return NULL;
}
/* Größte ID suchen */
apoint = (struct AreaNode *)KMSBase->AreaList.mlh_Head;
while(apoint->Node.mln_Succ)
{
if (apoint->AreaData.ID > previd)
previd = apoint->AreaData.ID;
apoint = apoint->Node.mln_Succ;
}
if (previd + 1 == 0) /* ID-Überlauf */
{
previd = 0; id = 0;
apoint = (struct AreaNode *)KMSBase->AreaList.mlh_Head;
id = apoint->AreaData.ID;
while(apoint->Node.mln_Succ && previd + 1 == id)
{
previd = id;
apoint = (struct AreaNode *)apoint->Node.mln_Succ;
if (apoint->Node.mln_Succ)
id = apoint->AreaData.ID;
}
}
if (previd == id)
{
SystemError("InsertArea", "Too many areas!");
return NULL;
}
if (!(newapoint = (struct AreaNode *)AllocMem((ULONG)sizeof(struct AreaNode),MEMF_PUBLIC|MEMF_CLEAR)))
{
SystemError("InsertArea", "Out of memory!");
return NULL;
}
newapoint->AreaData.ID = previd + 1;
Insert((struct List *)&KMSBase->AreaList, (struct Node *)newapoint, (struct Node *)apoint->Node.mln_Pred);
return newapoint;
}
///
/********************************
* Areastruktur löschen *
* TakeASem() von außen *
********************************
* I: struct AreaNode * *
* O: --- *
********************************/
/// "DeleteArea"
VOID DeleteArea(struct AreaNode *target)
{
if (!target)
return;
KMSBase->Modified |= MODIFIED_AREAS;
Remove((struct Node *)target);
FreeMem(target, (ULONG)sizeof(struct AreaNode));
}
///
/********************************
* Area editieren/anlegen *
********************************
* I: Name, Flag (alt/neu) *
* O: struct AreaNode * *
* O: FALSE bei Fehler *
********************************/
/// "EditArea"
BOOL EditArea(STRPTR name, UWORD flag)
{
struct AreaNode *current;
if (!(current = KMS_LC->Session.CurrentArea))
{
SystemError("EditArea", "No CurrentArea!");
return FALSE;
}
Upper(name);
if (name)
{
/* Angegebenes Brett edieren bzw. neu anlegen */
if (strchr(name, '/') || strchr(name, '.'))
{
SysMsg(AREANAME_ONLY);
return FALSE;
}
struct AreaNode *result = NULL;
TakeASem(FALSE);
if (current->AreaData.Daughter)
{
result = SetArea(current->AreaData.Daughter);
while(result && stricmp(result->AreaData.Name, name))
{
if (result->AreaData.Next)
result = SetArea(result->AreaData.Next);
else
result = NULL;
}
}
DropASem();
if (result)
{
if (flag & AED_NEW)
{
SysMsg(AREA_ALREADY_EXISTS);
return FALSE;
}
/* Edieren */
SysMsg(EDIT_OLD_AREA);
if (EditAreaInfo(result))
return TRUE;
else
return FALSE;
}
else
{
if (flag & AED_OLD)
{
SysMsg(AREA_NOT_FOUND);
return FALSE;
}
/* Neu anlegen */
TakeASem(TRUE);
if (result = InsertArea())
{
DropASem();
SysMsg(EDIT_NEW_AREA);
strncpy(result->AreaData.Name, name, sizeof(result->AreaData.Name) - 1);
result->AreaData.Name[sizeof(result->AreaData.Name) - 1] = '\0';
result->AreaData.Type = ATYPE_NEWS;
result->AreaData.QuoteStr = 1;
result->AreaData.PQuoteStr = 1;
result->AreaData.ResendStr = 1;
result->AreaData.ForwardStr = 1;
result->AreaData.OriginStr = 1;
if (!EditAreaInfo(result))
{
DeleteArea(result);
return FALSE;
}
TakeASem(TRUE);
if (!current->AreaData.Daughter)
{
/* Neue erste Tochter */
current->AreaData.Daughter = result->AreaData.ID;
result->AreaData.Mother = current->AreaData.ID;
result->AreaData.Next = 0;
}
else
{
/* Weitere Tochter einsortieren */
struct AreaNode *daughter = SetArea(current->AreaData.Daughter);
struct AreaNode *predaughter = NULL;
while(daughter && stricmp(result->AreaData.Name,daughter->AreaData.Name) != -1)
{
predaughter = daughter;
if (daughter->AreaData.Next)
daughter = SetArea(daughter->AreaData.Next);
else
daughter = NULL;
}
result->AreaData.Mother = current->AreaData.ID;
if (!predaughter)
{
/* Neue Area ist die erste */
result->AreaData.Next = daughter->AreaData.ID;
current->AreaData.Daughter = result->AreaData.ID;
}
else if (!daughter)
{
/* Neue Area ist die letzte */
predaughter->AreaData.Next = result->AreaData.ID;
result->AreaData.Next = 0;
}
else
{
/* Neue Area zwischen predaughter und daughter einhängen */
predaughter->AreaData.Next = result->AreaData.ID;
result->AreaData.Next = daughter->AreaData.ID;
}
}
DropASem();
return TRUE;
}
else
{
DropASem();
SysMsg(EDIT_NEW_FAILED);
return FALSE;
}
}
}
else
{
/* Aktuelles Brett editieren */
SysMsg(EDIT_OLD_AREA);
if (EditAreaInfo(current))
{
KMS_LC->Session.CurrentAccess = CheckAccess(current);
return TRUE;
}
else
return FALSE;
}
}
///
/********************************
* Area-Info editieren *
********************************
* I: struct AreaNode * *
* O: FALSE: Plop/ShutDown *
********************************/
/// "EditAreaInfo"
BOOL EditAreaInfo(struct AreaNode *target)
{
LONG result;
struct Area area;
KMSBase->Modified |= MODIFIED_AREAS;
area = target->AreaData;
CmdInput(NULL, PROMPT_ANAME, "/.", area.Name, sizeof(area.Name)-1, INF_PROMPT|INF_UPCASE|INF_NOEMPTY|INF_EXCLUDE|INF_DEFBUF);
if (Plop || ShutDown)
return FALSE;
strcpy(area.Name, KMS_LC->Session.InputBuffer);
CmdInput(NULL, PROMPT_AINFO, NULL, area.Info, sizeof(area.Info)-1, INF_PROMPT|INF_DEFBUF);
if (Plop || ShutDown)
return FALSE;
strcpy(area.Info, KMS_LC->Session.InputBuffer);
TEXT tmp[LEN_NUMBER+1];
TEXT def[2];
if (area.ID != 1)
{
CmdInput(NULL, PROMPT_AMBNAME, NULL, area.MBName, sizeof(area.MBName)-1, INF_PROMPT|INF_NOEMPTY|INF_DEFBUF);
if (Plop || ShutDown)
return FALSE;
strcpy(area.MBName, KMS_LC->Session.InputBuffer);
tmp[0] = KMSBase->AFlags[AFLAG_NEWS];
tmp[1] = KMSBase->AFlags[AFLAG_FILES];
tmp[2] = '\0';
if (area.Type & ATYPE_NEWS)
def[0] = KMSBase->AFlags[AFLAG_NEWS];
else if (area.Type & ATYPE_FILES)
def[0] = KMSBase->AFlags[AFLAG_FILES];
else
def[0] = '\0';
def[1] = '\0';
CmdInput(NULL, PROMPT_ATYPE, tmp, def, 1, INF_PROMPT|INF_UPCASE);
if (Plop || ShutDown)
return FALSE;
area.Type &= ATYPE_GROUP;
if (*KMS_LC->Session.InputBuffer == KMSBase->AFlags[AFLAG_NEWS])
area.Type |= ATYPE_NEWS;
else if (*KMS_LC->Session.InputBuffer == KMSBase->AFlags[AFLAG_FILES])
area.Type |= ATYPE_FILES;
if (area.Type & ATYPE_GROUP)
strcpy(def, KMSBase->Yes);
else
strcpy(def, KMSBase->No);
CmdInput(NULL, PROMPT_USERGROUP, KMSBase->YNText, def, 1, INF_PROMPT|INF_UPCASE);
if (Plop || ShutDown)
return FALSE;
if (*KMS_LC->Session.InputBuffer == KMSBase->YNText[YES])
area.Type |= ATYPE_GROUP;
else
area.Type &= ~ATYPE_GROUP;
}
else
{
/* Root -> Private Post */
*area.MBName = '\0'; /* Netmail -> Leerer Name */
area.Type = ATYPE_PRIVATE;
}
if (area.Type & (ATYPE_FILES|ATYPE_PRIVATE))
{
BOOL ok = FALSE;
do
{
CmdInput(NULL, PROMPT_AFPATH, NULL, area.FilePath, sizeof(area.FilePath)-1, INF_PROMPT|INF_DEFBUF);
if (Plop || ShutDown)
return FALSE;
if (DirExists(KMS_LC->Session.InputBuffer))
{
strcpy(area.FilePath, KMS_LC->Session.InputBuffer);
ok = TRUE;
}
else
SysMsg(INVALID_DIR);
}
while(!ok);
}
sprintf(tmp, "%d", area.ReadLevel);
result = CmdInput(NULL, PROMPT_AREAD, NULL, tmp, 3, INF_PROMPT|INF_NUMERIC);
if (Plop || ShutDown)
return FALSE;
area.ReadLevel = (UWORD)result;
sprintf(tmp, "%d", area.WriteLevel);
result = CmdInput(NULL, PROMPT_AWRITE, NULL, tmp, 3, INF_PROMPT|INF_NUMERIC);
if (Plop || ShutDown)
return FALSE;
area.WriteLevel = (UWORD)result;
sprintf(tmp, "%d", area.EditLevel);
result = CmdInput(NULL, PROMPT_AEDIT, NULL, tmp, 3, INF_PROMPT|INF_NUMERIC);
if (Plop || ShutDown)
return FALSE;
area.EditLevel = (UWORD)result;
sprintf(tmp, "%d", area.HoldNum);
result = CmdInput(NULL, PROMPT_AHNUM, NULL, tmp, 4, INF_PROMPT|INF_NUMERIC);
if (Plop || ShutDown)
return FALSE;
area.HoldNum = (UWORD)result;
sprintf(tmp, "%d", area.HoldDays);
result = CmdInput(NULL, PROMPT_AHDAYS, NULL, tmp, 4, INF_PROMPT|INF_NUMERIC);
if (Plop || ShutDown)
return FALSE;
area.HoldDays = (UWORD)result;
area.AccessBits = SetAccessBits(area.AccessBits, PROMPT_ABITS);
if (Plop || ShutDown)
return FALSE;
if (area.ID != 1)
{
if (area.WriteFlag & AWF_TONAME)
strcpy(def, KMSBase->Yes);
else
strcpy(def, KMSBase->No);
CmdInput(NULL, PROMPT_ATONAME, KMSBase->YNText, def, 1, INF_PROMPT|INF_UPCASE);
if (Plop || ShutDown)
return FALSE;
if (*KMS_LC->Session.InputBuffer == KMSBase->YNText[YES])
area.WriteFlag |= AWF_TONAME;
else
area.WriteFlag &= ~AWF_TONAME;
}
if (area.WriteFlag & AWF_PSEUDO)
strcpy(def, KMSBase->Yes);
else
strcpy(def, KMSBase->No);
CmdInput(NULL, PROMPT_APSEUDO, KMSBase->YNText, def, 1, INF_PROMPT|INF_UPCASE);
if (Plop || ShutDown)
return FALSE;
if (*KMS_LC->Session.InputBuffer == KMSBase->YNText[YES])
area.WriteFlag |= AWF_PSEUDO;
else
area.WriteFlag &= ~AWF_PSEUDO;
if (area.WriteFlag & AWF_NORE)
strcpy(def, KMSBase->No);
else
strcpy(def, KMSBase->Yes);
CmdInput(NULL, PROMPT_ARE, KMSBase->YNText, def, 1, INF_PROMPT|INF_UPCASE);
if (Plop || ShutDown)
return FALSE;
if (*KMS_LC->Session.InputBuffer == KMSBase->YNText[YES])
area.WriteFlag &= ~AWF_NORE;
else
area.WriteFlag |= AWF_NORE;
sprintf(tmp, "%d", area.QuoteStr);
result = CmdInput(NULL, PROMPT_AQUOTES, NULL, tmp, 2, INF_PROMPT|INF_NUMERIC);
if (Plop || ShutDown)
return FALSE;
area.QuoteStr = (UWORD)result;
sprintf(tmp, "%d", area.PQuoteStr);
result = CmdInput(NULL, PROMPT_APQUOTES, NULL, tmp, 2, INF_PROMPT|INF_NUMERIC);
if (Plop || ShutDown)
return FALSE;
area.PQuoteStr = (UWORD)result;
sprintf(tmp, "%d", area.ResendStr);
result = CmdInput(NULL, PROMPT_ARESENDS, NULL, tmp, 2, INF_PROMPT|INF_NUMERIC);
if (Plop || ShutDown)
return FALSE;
area.ResendStr = (UWORD)result;
sprintf(tmp, "%d", area.ForwardStr);
result = CmdInput(NULL, PROMPT_AFORWS, NULL, tmp, 2, INF_PROMPT|INF_NUMERIC);
if (Plop || ShutDown)
return FALSE;
area.ForwardStr = (UWORD)result;
sprintf(tmp, "%d", area.OriginStr);
result = CmdInput(NULL, PROMPT_AORIGS, NULL, tmp, 2, INF_PROMPT|INF_NUMERIC);
if (Plop || ShutDown)
return FALSE;
area.OriginStr = (UWORD)result;
Forbid();
target->AreaData = area;
Permit();
return TRUE;
}
///
/********************************
* Area entfernen/löschen *
********************************
* I: STRPTR name *
* O: OK TRUE/FALSE *
********************************/
/// "RemoveArea"
BOOL RemoveArea(STRPTR name)
{
struct AreaNode *current;
if (!(current = KMS_LC->Session.CurrentArea))
{
SystemError("RemoveArea", "No CurrentArea!");
return FALSE;
}
if (!name)
{
/* Aktuelles Brett kann nicht gelöscht werden */
SysMsg(AREA_NOT_DELETED);
return FALSE;
}
else
{
/* Angegebenes Brett löschen */
if (strchr(name, '/') || strchr(name, '.'))
{
SysMsg(AREANAME_ONLY);
return FALSE;
}
struct AreaNode *result = NULL;
struct AreaNode *preresult = NULL;
TakeASem(FALSE);
if (current->AreaData.Daughter)
{
result = SetArea(current->AreaData.Daughter);
while(result && stricmp(result->AreaData.Name, name))
{
preresult = result;
if (result->AreaData.Next)
result = SetArea(result->AreaData.Next);
else
result = NULL;
}
}
if (!result)
{
/* Brett nicht vorhanden */
DropASem();
SysMsg(AREA_NOT_FOUND);
return FALSE;
}
else
{
/* Wenn zu löschendes Brett Unterbretter besitzt, Schluss */
if (result->AreaData.Daughter)
{
DropASem();
SysMsg(MOTHER_NOT_DELETED);
return FALSE;
}
/* Wenn Area momentan CurrentArea eines Users, nicht löschen */
TakeMSem(FALSE);
struct KMSNode *member = KMSBase->MemberList.mlh_Head;
while(member->Node.mln_Succ)
{
if (member->LCPtr->Session.CurrentArea == result)
{
DropMSem();
DropASem();
SysMsg(AREA_VISITOR);
return FALSE;
}
member = member->Node.mln_Succ;
}
DropMSem();
DropASem();
/* Nachrichten löschen? */
UMSMsgNum num;
if (num = SelectArea(result->AreaData.MBName))
{
TEXT buff[16];
sprintf(buff, "%ld", num);
PPArg = buff;
SysMsg(MSGS_FOUND);
PPArg = NULL;
if (YNRequest(DELETE_MSGS, FALSE))
{
num = UMSSelectTags(MyUMSAccount, UMSTAG_SelReadLocal, TRUE,
UMSTAG_SelMask, KMSLSTATF_InGroup|KMSLSTATF_Protected,
UMSTAG_SelMatch, KMSLSTATF_InGroup|KMSLSTATF_Protected,
TAG_DONE);
if (num)
{
sprintf(buff, "%ld", num);
PPArg = buff;
SysMsg(PROT_MSGS_FOUND);
PPArg = NULL;
if (YNRequest(DELETE_MSGS, FALSE))
DeleteMsg(result, DEL_ALL);
}
else
DeleteMsg(result, DEL_ALL);
}
}
SelectArea(KMS_LC->Session.CurrentArea->AreaData.MBName);
/* Wirklich Gruppe löschen? */
PPArg = name;
SysMsg(DELETING_AREA);
PPArg = NULL;
if (!YNRequest(REALLY_SURE, FALSE))
return FALSE;
/* Wenn zu löschendes Brett erstes Tochterbrett ist, */
/* dann Mutter auf nächste Tochter einstimmen ;-) */
TakeASem(TRUE);
if (result->AreaData.ID == current->AreaData.Daughter)
if (result->AreaData.Next)
current->AreaData.Daughter = result->AreaData.Next;
else
current->AreaData.Daughter = 0;
/* Wenn zu löschendes Brett nicht einziges Unterbrett, */
/* dann "Next"-Zeiger aktualisieren */
if (preresult)
preresult->AreaData.Next = result->AreaData.Next;
/* Jetzt löschen */
DeleteArea(result);
DropASem();
SysMsg(AREA_DELETED);
return TRUE;
}
}
}
///
/***************************************
* Brettliste *
***************************************
* I: path: Pfadstring *
* flag: ALIST_ALL, ALIST_NEXTNEW, *
* ALIST_WHOLE, ... *
* O: TRUE: OK, FALSE: Userbreak *
***************************************/
/// "ListAreas"
BOOL ListAreas(STRPTR path, UWORD flag)
{
BOOL titel = TRUE;
BOOL stop = FALSE;
BOOL userbreak = FALSE;
struct AreaNode *current, *current0;
UBYTE curraccess;
UWORD busycount = 0;
TakeASem(FALSE);
if (path)
{
current = ChangeArea(path);
if (!current)
{
DropASem();
SysMsg(INVALID_PATH);
return FALSE;
}
}
else
{
current = KMS_LC->Session.CurrentArea;
if (!current)
{
DropASem();
SystemError("ListAreas", "No CurrentArea!");
return FALSE;
}
}
if (!(flag & (ALIST_NEXTNEW|ALIST_NEXT|ALIST_NEXTSEL|ALIST_NEXTPROT)) && !current->AreaData.Daughter)
{
DropASem();
SysMsg(NO_AREAS_FOUND);
return FALSE;
}
current0 = current;
while(!userbreak && current)
{
/* Busy-Counter erhöhen, evt. Lebenszeichen geben */
if (titel && busycount++ == 10)
SysMsg(SEARCHING);
else if (titel && busycount > 10 && busycount % 2)
Print(".", PF_NOLF|PF_NOBRK);
/* Nächste Area */
if (current->AreaData.Daughter && !stop)
{
current = SetArea(current->AreaData.Daughter);
if (!(flag & ALIST_WHOLE))
stop = TRUE;
}
else if (current->AreaData.Next)
{
current = SetArea(current->AreaData.Next);
if (!(flag & ALIST_WHOLE))
stop = TRUE;
else
stop = FALSE;
}
else if (flag & ALIST_WHOLE)
{
if (current->AreaData.Mother)
current = SetArea(current->AreaData.Mother);
else
current = NULL;
stop = TRUE;
}
else
current = NULL;
if (current && !(flag & (ALIST_NEXTNEW|ALIST_NEXT|ALIST_NEXTSEL|ALIST_NEXTPROT)) && current->AreaData.Mother == current0->AreaData.Mother)
current = NULL;
/* Areadaten ausgeben */
if (current && (!stop || !(flag & ALIST_WHOLE)) && (curraccess = CheckAccess(current)))
{
SelectArea(current->AreaData.MBName);
/* Wenn passende Gruppe gefunden */
if (flag & (ALIST_ALL|ALIST_NEXT) || (flag & (ALIST_NEXTNEW|ALIST_NEW) && NextMsg(0, MLIST_NEW))
|| (flag & (ALIST_NEXTSEL|ALIST_SEL) && NextMsg(0, MLIST_SEL))
|| (flag & (ALIST_NEXTPROT|ALIST_PROT) && NextMsg(0, MLIST_PROT)))
{
if (titel)
{
if (!(flag & ALIST_QUIET))
{
if (flag & ALIST_ALL)
{
CreatePath(current0);
PPArg = PathString;
SysMsg(DIRLST_ALL);
PPArg = NULL;
}
else if (flag & ALIST_NEXT)
SysMsg(DIRLST_NEXT);
else if (flag & ALIST_NEW)
SysMsg(DIRLST_NEW);
else if (flag & ALIST_NEXTNEW)
SysMsg(DIRLST_NEXTNEW);
else if (flag & ALIST_SEL)
SysMsg(DIRLST_SEL);
else if (flag & ALIST_NEXTSEL)
SysMsg(DIRLST_NEXTSEL);
else if (flag & ALIST_PROT)
SysMsg(DIRLST_PROT);
else if (flag & ALIST_NEXTPROT)
SysMsg(DIRLST_NEXTPROT);
SysMsg(DIRLST_HEAD);
KMS_LC->Session.LineCounter = 6;
}
else if (busycount >= 10)
Print(NULL, 0);
titel = FALSE;
}
userbreak = PrintAreaInfo(current, curraccess);
/* Wechsel in nächstes Brett? */
if (flag & (ALIST_NEXTNEW|ALIST_NEXT|ALIST_NEXTSEL|ALIST_NEXTPROT))
{
KMS_LC->Session.CurrentArea = current;
KMS_LC->Session.CurrentAccess = curraccess;
if (KMS_LC->Session.CurrentUser->UserData.Flags & UF_AUTO_LIST)
{
Print(NULL, 0);
if (flag & ALIST_NEXTNEW)
userbreak = ListMsgs(current, MLIST_NEW);
else if (flag & ALIST_NEXTSEL)
userbreak = ListMsgs(current, MLIST_SEL);
else if (flag & ALIST_NEXTPROT)
userbreak = ListMsgs(current, MLIST_PROT);
}
current = NULL;
}
}
}
}
DropASem();
if (busycount >= 10 && titel)
Print(NULL, 0);
if (titel)
{
if (flag & ALIST_NEXTNEW)
SysMsg(NO_NEXTNEW_AREA);
else if (flag & ALIST_NEXTSEL)
SysMsg(NO_NEXTSEL_AREA);
else if (flag & ALIST_NEXTPROT)
SysMsg(NO_NEXTPROT_AREA);
else if (flag & ALIST_NEXT)
SysMsg(NO_NEXT_AREA);
else
SysMsg(NO_AREAS_FOUND);
userbreak = TRUE;
}
return !userbreak;
}
///
/***************************************
* Eine Zeile der Arealiste ausgeben *
***************************************
* I: struct AreaNode * *
* O: Abbruch durch CTRL-C/X: TRUE *
***************************************/
/// "PrintAreaInfo"
BOOL PrintAreaInfo(struct AreaNode *area, UBYTE curracc)
{
UBYTE result, type;
TEXT merk[LEN_KMSPATH+16], line[LEN_KMSPATH+16];
if (!area)
return FALSE;
/* Area-Typ und Zugriffs-Flags */
strcpy(merk, " - --- ");
type = area->AreaData.Type;
if (type & ATYPE_PRIVATE)
merk[1] = KMSBase->AFlags[AFLAG_PRIVATE]; /* 'P'rivate Post */
else if (type & ATYPE_FILES)
merk[1] = KMSBase->AFlags[AFLAG_FILES]; /* 'F'iles */
else if (type & ATYPE_NEWS)
merk[1] = KMSBase->AFlags[AFLAG_NEWS]; /* 'N'achrichten */
if (type & ATYPE_GROUP)
merk[2] = '!'; /* 'G'ruppenbrett */
if (curracc & AACC_READ)
merk[3] = KMSBase->AFlags[AFLAG_READ]; /* 'R'ead */
if (curracc & AACC_WRITE)
merk[4] = KMSBase->AFlags[AFLAG_WRITE]; /* 'W'rite */
if (curracc & AACC_EDIT)
merk[5] = KMSBase->AFlags[AFLAG_EDIT]; /* 'E'dit */
strcpy(line, merk);
/* Pfad-String konstruieren */
CreatePath(area);
strcat(line, PathString);
line[KMS_LC->Session.CurrentUser->UserData.LineLen] = '\0';
strcat(line, "\n");
/* Zeile ausgeben */
PPArg = line;
result = MsgParsePrint(KMSBase->AreaListPath, MP_NOWRAP);
PPArg = NULL;
if (!result)
{
TEXT info[LEN_AREAINFO+16];
sprintf(info, " %s\n",area->AreaData.Info);
PPArg = info;
result = MsgParsePrint(KMSBase->AreaListInfo, MP_NOWRAP);
PPArg = NULL;
}
return (BOOL)result;
}
///
/***************************************
* Aktuelles Brett wechseln *
***************************************
* I: STPRTR pfadangabe *
* O: Erfolg TRUE/FALSE *
***************************************/
/// "ChangePath"
BOOL ChangePath(STRPTR path)
{
UMSMsgNum num;
TEXT all[LEN_NUMBER+1];
TEXT new[LEN_NUMBER+1];
struct AreaNode *apoint = ChangeArea(path);
if (apoint)
{
SelectArea(apoint->AreaData.MBName);
KMS_LC->Session.CurrentArea = apoint;
KMS_LC->Session.CurrentAccess = CheckAccess(apoint);
ReadMsg(0, RF_RESET);
num = UMSSelectTags(MyUMSAccount, UMSTAG_SelReadLocal, TRUE,
UMSTAG_SelMask, KMSLSTATF_InGroup,
UMSTAG_SelMatch, KMSLSTATF_InGroup,
TAG_DONE);
sprintf(all, "%ld", num);
PPArg = all;
num = UMSSelectTags(MyUMSAccount, UMSTAG_SelReadLocal, TRUE,
UMSTAG_SelMask, KMSLSTATF_Unread|KMSLSTATF_InGroup,
UMSTAG_SelMatch, KMSLSTATF_Unread|KMSLSTATF_InGroup,
TAG_DONE);
sprintf(new, "%ld", num);
PPArg2 = new;
SysMsg(DIRLST_ACT);
PPArg2 = NULL;
PPArg = NULL;
SysMsg(DIRLST_HEAD);
PrintAreaInfo(apoint, KMS_LC->Session.CurrentAccess);
if (KMS_LC->Session.CurrentUser->UserData.Flags & UF_AUTO_AREALIST)
{
Print(NULL, 0);
ListAreas(NULL, ALIST_ALL);
}
return TRUE;
}
else
return FALSE;
}
///
/***************************************
* Pfad-String konstruieren *
***************************************
* I: struct AreaNode * *
* O: --- *
***************************************/
/// "CreatePath"
VOID CreatePath(struct AreaNode *area)
{
struct AreaNode *apoint;
TEXT merk[LEN_KMSPATH+1];
if (!area)
{
*PathString = '\0';
return;
}
/* Pfad-String konstruieren */
strcpy(PathString, area->AreaData.Name);
TakeASem(FALSE);
apoint = area;
while(apoint && apoint->AreaData.Mother && strlen(PathString) < LEN_KMSPATH)
{
apoint = SetArea(apoint->AreaData.Mother);
strcpy(merk, PathString);
if (apoint && apoint->AreaData.Mother)
strcpy(PathString, apoint->AreaData.Name);
else
strcpy(PathString, "");
strcat(PathString, "/");
strncat(PathString, merk, LEN_KMSPATH - strlen(merk));
PathString[LEN_KMSPATH] = '\0';
}
DropASem();
}
///
/*********************************
* Area wechseln *
*********************************
* I: Pfad *
* O: Neue Area *
*********************************/
/// "ChangeArea"
struct AreaNode *ChangeArea(STRPTR path)
{
struct AreaNode *current;
BOOL pathsearch = FALSE;
BOOL begin = TRUE;
TEXT token[LEN_AREANAME+1];
if (!path || !strlen(path))
return NULL;
if (!(current = KMS_LC->Session.CurrentArea))
{
SystemError("ChangeArea", "No CurrentArea!");
return NULL;
}
if (strchr(path, '/') || strchr(path, '.'))
{
/* Angegebenen Pfad streng verfolgen */
/* BRETT MAUS/AMIGA */
/* BRETT /MAUS/AMIGA */
/* BRETT / */
/* BRETT . */
TakeASem(FALSE);
do
{
path = PathParse(path, token);
if (!strcmp(token, "/") && begin)
{
/* Wechsel ins Hauptverzeichnis (Private Mail) */
current = SetArea(1);
}
if (strcmp(token, ".") && begin && *path) /* Wenn nicht "." allein angegeben war */
{
/* Wechsel ins Unterverzeichnis */
current = SetArea(current->AreaData.Daughter);
}
if (!strcmp(token, "/"))
{
/* Wechsel ins Unterverzeichnis */
if (!begin)
current = SetArea(current->AreaData.Daughter);
}
else if (!strcmp(token, "."))
{
/* Einen Zweig höher gehen */
current = SetArea(current->AreaData.Mother);
}
else
{
/* Brettname im aktuellen Verzeichnis suchen */
while(current && stricmp(current->AreaData.Name, token))
current = SetArea(current->AreaData.Next);
}
begin = FALSE;
} while(*path && current);
DropASem();
if (CheckAccess(current))
return current;
else
return NULL;
}
else
{
/* Einzelnes Brett global suchen: Ab aktuellem und dann, falls
nicht gefunden, von vorne */
current = SeekAreaName(current, path);
if (!current)
{
current = SetArea(1);
current = SeekAreaName(current, path);
}
if (CheckAccess(current))
return current;
else
return NULL;
}
}
///
/*********************************************
* Nächsten Brettnamen aus Pfadangabe ziehen *
*********************************************
* I: Pfadstring, Tokenbuffer *
* O: Modifizierter Pfadstring *
*********************************************/
/// "PathParse"
STRPTR PathParse(STRPTR string, STRPTR tok)
{
UWORD n = 0;
*tok = '\0';
if (*string == '/' || *string == '.')
{
tok[0] = *string;
tok[1] = '\0';
return ++string;
}
while(*string && *string != '/' && *string != '.')
{
tok[n++] = *string;
string++;
}
tok[n] = '\0';
return string;
}
///
/*******************************************
* Area mit bestimmtem Namen global suchen *
*******************************************
* I: Start-Area, Name *
* O: Gefundene Area oder NULL *
*******************************************/
/// "SeekAreaName"
struct AreaNode *SeekAreaName(struct AreaNode *current, STRPTR name)
{
BOOL goon = TRUE;
BOOL stop = FALSE;
TEXT buf[LEN_AREANAME+1];
UWORD len;
TakeASem(FALSE);
while(current && goon)
{
if (current->AreaData.Daughter && !stop)
{
current = SetArea(current->AreaData.Daughter);
stop = FALSE;
}
else if (current->AreaData.Next)
{
current = SetArea(current->AreaData.Next);
stop = FALSE;
}
else
{
current = SetArea(current->AreaData.Mother);
stop = TRUE;
}
len = strlen(name);
if (len > LEN_AREANAME)
len = LEN_AREANAME;
strncpy(buf, current->AreaData.Name, len);
buf[len] = '\0';
if (current && (!stop || !current->AreaData.Mother) && !stricmp(buf, name))
goon = FALSE;
}
DropASem();
return current;
}
///
/*******************************************
* UMS-MsgBase-Namen global suchen *
*******************************************
* I: gesuchte Area *
* O: AreaNode *
*******************************************/
/// "AreaSearch"
struct AreaNode *AreaSearch(STRPTR name)
{
struct AreaNode *apoint;
TakeASem(FALSE);
apoint = (struct AreaNode *)KMSBase->AreaList.mlh_Head;
while(apoint->Node.mln_Succ)
{
if (!stricmp(name, apoint->AreaData.MBName))
{
DropASem();
return apoint;
}
apoint = apoint->Node.mln_Succ;
}
DropASem();
return NULL;
}
///
/*********************************
* Aenderungen in mehreren Areas *
*********************************
* I: Pfad, Flag *
* O: Erfolg TRUE/FALSE *
*********************************/
/// "AreaModify"
BOOL AreaModify(STRPTR path, UWORD flag)
{
LONG result;
ULONG bits;
if (path && !ChangeArea(path))
{
SysMsg(INVALID_PATH);
return FALSE;
}
result = CmdInput(NULL, PROMPT_AREAD, NULL, "", 3, INF_PROMPT|INF_NUMERIC);
if (Plop || ShutDown)
return FALSE;
if (strlen(KMS_LC->Session.InputBuffer))
return GlobalAreaChange(path, flag, GAC_RLEVEL, result);
result = CmdInput(NULL, PROMPT_AWRITE, NULL, "", 3, INF_PROMPT|INF_NUMERIC);
if (Plop || ShutDown)
return FALSE;
if (strlen(KMS_LC->Session.InputBuffer))
return GlobalAreaChange(path, flag, GAC_WLEVEL, result);
result = CmdInput(NULL, PROMPT_AEDIT, NULL, "", 3, INF_PROMPT|INF_NUMERIC);
if (Plop || ShutDown)
return FALSE;
if (strlen(KMS_LC->Session.InputBuffer))
return GlobalAreaChange(path, flag, GAC_ELEVEL, result);
result = CmdInput(NULL, PROMPT_AHNUM, NULL, "", 4, INF_PROMPT|INF_NUMERIC);
if (Plop || ShutDown)
return FALSE;
if (strlen(KMS_LC->Session.InputBuffer))
return GlobalAreaChange(path, flag, GAC_HNUM, result);
result = CmdInput(NULL, PROMPT_AHDAYS, NULL, "", 4, INF_PROMPT|INF_NUMERIC);
if (Plop || ShutDown)
return FALSE;
if (strlen(KMS_LC->Session.InputBuffer))
return GlobalAreaChange(path, flag, GAC_HDAYS, result);
bits = SetAccessBits(0, PROMPT_AADDBITS);
if (Plop || ShutDown)
return FALSE;
if (bits)
return GlobalAreaChange(path, flag, GAC_ADDBITS, bits);
bits = SetAccessBits(0, PROMPT_ADELBITS);
if (Plop || ShutDown)
return FALSE;
if (bits)
return GlobalAreaChange(path, flag, GAC_DELBITS, bits);
CmdInput(NULL, PROMPT_ATONAME, KMSBase->YNText, "", 1, INF_PROMPT|INF_UPCASE);
if (Plop || ShutDown)
return FALSE;
if (*KMS_LC->Session.InputBuffer == KMSBase->YNText[YES])
return GlobalAreaChange(path, flag, GAC_WFTONAME, 1);
else if (* KMS_LC->Session.InputBuffer == KMSBase->YNText[NO])
return GlobalAreaChange(path, flag, GAC_WFTONAME, 0);
CmdInput(NULL, PROMPT_APSEUDO, KMSBase->YNText, "", 1, INF_PROMPT|INF_UPCASE);
if (Plop || ShutDown)
return FALSE;
if (*KMS_LC->Session.InputBuffer == KMSBase->YNText[YES])
return GlobalAreaChange(path, flag, GAC_WFPSEUDO, 1);
else if (* KMS_LC->Session.InputBuffer == KMSBase->YNText[NO])
return GlobalAreaChange(path, flag, GAC_WFPSEUDO, 0);
CmdInput(NULL, PROMPT_ARE, KMSBase->YNText, "", 1, INF_PROMPT|INF_UPCASE);
if (Plop || ShutDown)
return FALSE;
if (*KMS_LC->Session.InputBuffer == KMSBase->YNText[YES])
return GlobalAreaChange(path, flag, GAC_WFNORE, 1);
else if (* KMS_LC->Session.InputBuffer == KMSBase->YNText[NO])
return GlobalAreaChange(path, flag, GAC_WFNORE, 0);
result = CmdInput(NULL, PROMPT_AQUOTES, NULL, "", 2, INF_PROMPT|INF_NUMERIC);
if (Plop || ShutDown)
return FALSE;
if (strlen(KMS_LC->Session.InputBuffer))
return GlobalAreaChange(path, flag, GAC_QUOTES, result);
result = CmdInput(NULL, PROMPT_APQUOTES, NULL, "", 2, INF_PROMPT|INF_NUMERIC);
if (Plop || ShutDown)
return FALSE;
if (strlen(KMS_LC->Session.InputBuffer))
return GlobalAreaChange(path, flag, GAC_PQUOTES, result);
result = CmdInput(NULL, PROMPT_ARESENDS, NULL, "", 2, INF_PROMPT|INF_NUMERIC);
if (Plop || ShutDown)
return FALSE;
if (strlen(KMS_LC->Session.InputBuffer))
return GlobalAreaChange(path, flag, GAC_RESENDS, result);
result = CmdInput(NULL, PROMPT_AFORWS, NULL, "", 2, INF_PROMPT|INF_NUMERIC);
if (Plop || ShutDown)
return FALSE;
if (strlen(KMS_LC->Session.InputBuffer))
return GlobalAreaChange(path, flag, GAC_FORWS, result);
result = CmdInput(NULL, PROMPT_AORIGS, NULL, "", 2, INF_PROMPT|INF_NUMERIC);
if (Plop || ShutDown)
return FALSE;
if (strlen(KMS_LC->Session.InputBuffer))
return GlobalAreaChange(path, flag, GAC_ORIGS, result);
return TRUE;
}
///
/*********************************
* Aenderungen in mehreren Areas *
*********************************
* I: Pfad, Flag, Code, Wert *
* O: Erfolg TRUE/FALSE *
*********************************/
/// "GlobalAreaChange"
BOOL GlobalAreaChange(STRPTR path, UWORD flag, UWORD code, ULONG value)
{
BOOL titel = TRUE;
BOOL stop = FALSE;
TakeASem(FALSE);
struct AreaNode *current, *current0;
if (path)
{
current = ChangeArea(path);
if (!current)
{
DropASem();
SysMsg(INVALID_PATH);
return FALSE;
}
}
else
{
current = KMS_LC->Session.CurrentArea;
if (!current)
{
DropASem();
SystemError("ListAreas", "No CurrentArea!");
return FALSE ;
}
}
if (!current->AreaData.Daughter)
{
DropASem();
SysMsg(NO_AREAS_FOUND);
return FALSE;
}
KMSBase->Modified |= MODIFIED_AREAS;
current0 = current;
while(current)
{
/* Nächste Area */
if (current->AreaData.Daughter && !stop)
{
current = SetArea(current->AreaData.Daughter);
if (!(flag & ALIST_WHOLE))
stop = TRUE;
}
else if (current->AreaData.Next)
{
current = SetArea(current->AreaData.Next);
if (!(flag & ALIST_WHOLE))
stop = TRUE;
else
stop = FALSE;
}
else if (flag & ALIST_WHOLE)
{
if (current->AreaData.Mother)
current = SetArea(current->AreaData.Mother);
else
current = NULL;
stop = TRUE;
}
else
current = NULL;
if (current && current->AreaData.Mother == current0->AreaData.Mother)
current = NULL;
/* Areadaten ausgeben */
if (current && (!stop || !(flag & ALIST_WHOLE)))
{
/* Wenn passende Gruppe gefunden */
SelectArea(current->AreaData.MBName);
if (titel)
{
SysMsg(DIRLST_MOD);
SysMsg(DIRLST_HEAD);
KMS_LC->Session.LineCounter = 6;
titel = FALSE;
}
PrintAreaInfo(current, CheckAccess(current));
if (code & (GAC_RLEVEL|GAC_WLEVEL|GAC_ELEVEL))
if (value > 255)
value = 255;
if (code & GAC_RLEVEL)
current->AreaData.ReadLevel = (UBYTE)value;
if (code & GAC_WLEVEL)
current->AreaData.WriteLevel = (UBYTE)value;
if (code & GAC_ELEVEL)
current->AreaData.EditLevel = (UBYTE)value;
else if (code & GAC_HNUM)
current->AreaData.HoldNum = (UBYTE)value;
else if (code & GAC_HDAYS)
current->AreaData.HoldDays = (UBYTE)value;
else if (code & GAC_DELBITS)
current->AreaData.AccessBits &= ~value;
else if (code & GAC_ADDBITS)
current->AreaData.AccessBits |= value;
else if (code & GAC_WFTONAME)
{
if (value == 1)
current->AreaData.WriteFlag |= AWF_TONAME;
else
current->AreaData.WriteFlag &= ~AWF_TONAME;
}
else if (code & GAC_WFPSEUDO)
{
if (value == 1)
current->AreaData.WriteFlag |= AWF_PSEUDO;
else
current->AreaData.WriteFlag &= ~AWF_PSEUDO;
}
else if (code & GAC_WFNORE)
{
if (value == 1)
current->AreaData.WriteFlag &= ~AWF_NORE;
else
current->AreaData.WriteFlag |= AWF_NORE;
}
else if (code & GAC_QUOTES)
current->AreaData.QuoteStr = (UBYTE)value;
else if (code & GAC_PQUOTES)
current->AreaData.PQuoteStr = (UBYTE)value;
else if (code & GAC_RESENDS)
current->AreaData.ResendStr = (UBYTE)value;
else if (code & GAC_FORWS)
current->AreaData.ForwardStr = (UBYTE)value;
else if (code & GAC_ORIGS)
current->AreaData.OriginStr = (UBYTE)value;
}
}
DropASem();
if (titel)
SysMsg(NO_AREAS_FOUND);
return TRUE;
}
///
/// "TakeASem"
VOID TakeASem(BOOL exclusive)
{
if (exclusive)
ObtainSemaphore(&KMSBase->AreaSem);
else
ObtainSemaphoreShared(&KMSBase->AreaSem);
}
///
/// "DropASem"
VOID DropASem(VOID)
{
ReleaseSemaphore(&KMSBase->AreaSem);
}
///